﻿package com.rbac.system.config;

import com.rbac.system.common.RequireDataPermission;
import com.rbac.system.common.RequirePermission;
import com.rbac.system.service.DataPermissionService;
import com.rbac.system.service.PermissionService;
import com.rbac.system.util.UserContextUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权限拦截器
 * 处理@RequirePermission注解的权限验证
 */
@Component
public class PermissionInterceptor implements HandlerInterceptor {
    
    @Autowired
    private UserContextUtil userContextUtil;
    
    @Autowired
    private PermissionService permissionService;

    @Autowired
    private DataPermissionService dataPermissionService;

    @Autowired
    private ObjectMapper objectMapper;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是HandlerMethod，直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        
        // 检查方法上是否有@RequirePermission注解
        RequirePermission requirePermission = method.getAnnotation(RequirePermission.class);
        if (requirePermission == null) {
            // 检查类上是否有@RequirePermission注解
            requirePermission = handlerMethod.getBeanType().getAnnotation(RequirePermission.class);
        }
        
        // 如果没有权限注解，直接放行
        if (requirePermission == null) {
            return true;
        }
        
        // 检查用户是否已认证
        if (!userContextUtil.isAuthenticated()) {
            writeErrorResponse(response, 401, "用户未登录");
            return false;
        }
        
        // 获取当前用户ID
        Long userId = userContextUtil.getCurrentUserId();
        if (userId == null) {
            writeErrorResponse(response, 401, "获取用户信息失败");
            return false;
        }
        
        // 获取用户权限列表
        List<String> userPermissions = permissionService.getUserPermissions(userId);
        
        // 检查用户是否拥有所需权限
        String requiredPermission = requirePermission.value();
        if (!userPermissions.contains(requiredPermission)) {
            writeErrorResponse(response, 403, "权限不足，需要权限：" + requiredPermission);
            return false;
        }

        // 检查数据权限
        RequireDataPermission dataPermission = method.getAnnotation(RequireDataPermission.class);
        if (dataPermission != null) {
            if (!checkDataPermission(request, userId, dataPermission)) {
                writeErrorResponse(response, 403, "数据权限不足");
                return false;
            }
        }

        return true;
    }
    
    /**
     * 检查数据权限
     */
    private boolean checkDataPermission(HttpServletRequest request, Long userId, RequireDataPermission dataPermission) {
        try {
            // 从请求路径中提取资源ID
            String pathInfo = request.getRequestURI();
            String[] pathParts = pathInfo.split("/");

            // 简化实现：假设资源ID在路径的最后一部分
            Long resourceId = null;
            if (pathParts.length > 0) {
                String lastPart = pathParts[pathParts.length - 1];
                try {
                    resourceId = Long.parseLong(lastPart);
                } catch (NumberFormatException e) {
                    // 如果最后一部分不是数字，可能是其他操作，暂时允许通过
                    return true;
                }
            }

            // 如果没有资源ID，检查是否为列表查询等操作
            if (resourceId == null) {
                // 对于列表查询，检查用户是否有基本权限
                return dataPermissionService.hasDataPermission(userId, dataPermission.resourceType(),
                        null, dataPermission.value());
            }

            // 检查对特定资源的权限
            return dataPermissionService.hasDataPermission(userId, dataPermission.resourceType(),
                    resourceId, dataPermission.value());
        } catch (Exception e) {
            // 权限检查出错时，默认拒绝访问
            return false;
        }
    }

    /**
     * 写入错误响应
     */
    private void writeErrorResponse(HttpServletResponse response, int code, String message) throws IOException {
        response.setStatus(code);
        response.setContentType("application/json;charset=UTF-8");

        Map<String, Object> result = new HashMap<>();
        result.put("code", code);
        result.put("message", message);
        result.put("data", null);

        response.getWriter().write(objectMapper.writeValueAsString(result));
    }
} 

